
package com.yami.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yami.shop.bean.dto.AreaDto;
import com.yami.shop.bean.model.Area;
import com.yami.shop.dao.AreaMapper;
import com.yami.shop.service.AreaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author lgh on 2018/10/26.
 */
@Service
public class AreaServiceImpl extends ServiceImpl<AreaMapper, Area> implements AreaService {

    @Autowired
    private AreaMapper areaMapper;

    @Override
    @Cacheable(cacheNames = "area", key = "#pid + ':' + #level")
    public List<Area> listByPid(Long pid, Integer level) {
        List<Area> areas = areaMapper.listByPid(pid, level);
        // 过滤没有子地区的二级地区
        if (areas.size() > 0 && areas.get(0).getLevel().equals(2)) {
            final Iterator<Area> iterator = areas.iterator();
            while (iterator.hasNext()) {
                Area area = iterator.next();
                List<Area> areaList = areaMapper.listByPid(area.getAreaId(), level);
                if (areaList.size() == 0) {
                    iterator.remove();
                }
            }
        }
        return areas;
//        return areaMapper.selectList(new LambdaQueryWrapper<Area>().eq(Area::getParentId, pid));
    }

    @Override
    @CacheEvict(cacheNames = "area", key = "#pid + ':' + #level")
    public void removeAreaCacheByParentId(Long pid, Integer level) {

    }

    @Override
    @Caching(evict = {
            @CacheEvict(cacheNames = "area", key = "'areaList'"),
            @CacheEvict(cacheNames = "area", key = "'areaProvinceList'"),
            @CacheEvict(cacheNames = "area", key = "'allAreaList'")
    })
    public void removeAreaListCache() {
    }

    @Override
    @Cacheable(cacheNames = "area", key = "'areaList'")
    public List<AreaDto> getAreaListInfo() {
        List<AreaDto> areaList = areaMapper.getAreaListInfo();
        for (AreaDto province : areaList) {
            List<Long> cityAll = Lists.newArrayList();
            for (AreaDto city : province.getAreas()) {
                cityAll.add(city.getAreaId());
                List<Long> areaAll = Lists.newArrayList();
                for (AreaDto area : city.getAreas()) {
                    areaAll.add(area.getAreaId());
                }
                city.setAreaIds(areaAll);
            }
            province.setAreaIds(cityAll);
        }
        return areaList;
    }

    @Override
    @Cacheable(cacheNames = "area", key = "'areaProvinceList'")
    public List<Area> getProvinceInfoList() {
        List<Area> areaList = areaMapper.selectList(new LambdaQueryWrapper<Area>().eq(Area::getLevel, 1));
        return areaList;
    }

    @Override
    public List<AreaDto> listAreaOfEnable() {
        return areaMapper.listAreaOfEnable();
    }

    @Override
    @Cacheable(cacheNames = "area", key = "'allAreaList'")
    public List<AreaDto> getAllAreaList(){
        List<AreaDto> allAreaList = areaMapper.getAllAreaList();
        Map<Long, List<AreaDto>> areaMap = allAreaList.stream().collect(Collectors.groupingBy(AreaDto::getParentId));
        List<AreaDto> regionList = areaMap.get(0L);
        if (CollUtil.isEmpty(regionList)) {
            return new ArrayList<>();
        }
        Iterator<AreaDto> iterator = regionList.iterator();
        while (iterator.hasNext()) {
            AreaDto AreaDto = iterator.next();
            List<AreaDto> areaList = areaMap.get(AreaDto.getAreaId());
            if (CollUtil.isEmpty(areaList)) {
                iterator.remove();
                continue;
            }
            extracted(areaList, areaMap);
            if (CollUtil.isEmpty(areaList)) {
                iterator.remove();
                continue;
            }
            AreaDto.setAreas(areaList);
            List<Long> areaIdsList = new ArrayList<>();
            areaList.forEach(s->areaIdsList.add(s.getAreaId()));
            AreaDto.setAreaIds(areaIdsList);
        }
        return regionList;
    }

    private void extracted(List<AreaDto> list, Map<Long, List<AreaDto>> areaMap) {
        Iterator<AreaDto> iterator = list.iterator();
        while (iterator.hasNext()) {
            AreaDto AreaDto = iterator.next();
            if (!areaMap.containsKey(AreaDto.getAreaId())) {
                iterator.remove();
                continue;
            }
            List<AreaDto> cityList = new ArrayList<>();
            List<Long>  areaids = new ArrayList<>();
            for (AreaDto city : areaMap.get(AreaDto.getAreaId())) {
                if (!areaMap.containsKey(city.getAreaId())) {
                    continue;
                }
                city.setAreas(areaMap.get(city.getAreaId()));
                List<Long> areaIdsList = new ArrayList<>();
                city.getAreas().forEach(s->areaIdsList.add(s.getAreaId()));
                city.setAreaIds(areaIdsList);
                cityList.add(city);
                areaids.add(city.getAreaId());
            }
            if (CollUtil.isEmpty(cityList)) {
                iterator.remove();
                continue;
            }
            AreaDto.setAreas(cityList);
            AreaDto.setAreaIds(areaids);
        }
    }
}
